import { ClampToEdgeWrapping, FrontSide, LinearFilter, LinearMipMapLinearFilter, Mesh, MeshBasicMaterial, PlaneGeometry, Texture, TextureLoader } from "three";
import GeoUtils from "../utils/GeoUtils";
import MeshUtil from "../utils/MeshUtil";
import NetUtil from "../utils/NetUtil";

/**
 * 影像瓦片Mesh
 */
export default class ImageTileMesh extends Mesh {
    private imageRequest;
    private param: { tileNum: { x: number, y: number, z: number }, urlBase: string, callback?: Function };
    public relationCount: number = 0; //层级切换时，瓦片亲戚节点的数量

    public constructor(param: { tileNum: { x: number, y: number, z: number }, urlBase: string, callback?: Function }) {
        super()
        this.param = param;

        //计算出瓦片在web墨卡托坐标系的中心点
        let xCenter = GeoUtils.getCDevX(param.tileNum.x, param.tileNum.z, 0.5);
        let yCenter = GeoUtils.getRDevY(param.tileNum.y, param.tileNum.z, 0.5);

        //把web墨卡托坐标系的中心点转换到ecef坐标系
        let ecefCenterPoint = GeoUtils.webToEcef(xCenter, yCenter);
        this.position.copy(ecefCenterPoint);

        let tileWidth = GeoUtils.getTileWidth(param.tileNum.z) + 0;
        let widthSegments = 10;
        let geometry = new PlaneGeometry(tileWidth, tileWidth, widthSegments, widthSegments);
        // 获取顶点位置属性
        const positionAttribute = geometry.attributes.position;

        let tempWebX, tempWebY, tempEcef;
        // 遍历所有几何体的所有顶点并修改顶点
        for (let i = 0; i < positionAttribute.count; i++) {
            const x = positionAttribute.getX(i);
            const y = positionAttribute.getY(i);

            tempWebX = xCenter + x;
            tempWebY = yCenter + y;
            tempEcef = GeoUtils.webToEcef(tempWebX, tempWebY);
            let currentGeometryPoint = tempEcef.sub(ecefCenterPoint);
            positionAttribute.setXYZ(i, currentGeometryPoint.x, currentGeometryPoint.y, currentGeometryPoint.z);
        }

        // 更新法线和渲染数据
        geometry.computeVertexNormals(); // 重新计算法线
        positionAttribute.needsUpdate = true; // 标记位置数据已更新
        this.geometry = geometry;

        let material = new MeshBasicMaterial({
            // wireframe: true, // 这会导致只显示线框
            color: '#FFFFFF',
            transparent: false,
            opacity: 1,
            side: FrontSide,
            depthTest: true,
            colorWrite: true,
            visible: false,
        });

        let url = param.urlBase + param.tileNum.z + '/' + param.tileNum.y + '/' + param.tileNum.x;
        let self = this;
        let texture = NetUtil.createTexture(url, (isSuccess, texture: Texture) => {
            if (isSuccess == true) {
                texture.minFilter = LinearMipMapLinearFilter; //NearestMipMapNearestFilter;//LinearMipMapLinearFilter; // 使用带mipmap的过滤方式
                texture.magFilter = LinearFilter;
                texture.wrapS = ClampToEdgeWrapping;//RepeatWrapping;
                texture.wrapT = ClampToEdgeWrapping;//RepeatWrapping;
                texture.generateMipmaps = true; // 启用mipmap生成
                // texture.flipY = false;
                texture.colorSpace = 'srgb';
                material.visible = true;
                material.needsUpdate = true;
                self.imageRequest = texture['imageLoader'] = null;
                
                if (this.param.callback) {
                    this.param.callback(self);
                    this.param.callback = null;
                }
                
            }
        });
        this.imageRequest = texture['imageLoader'];
        material.map = texture;
        this.material = material;
    }

    public dispose() {
        if(this.param.callback){ //this.relationCount > 0 && 
            this.param.callback(this);
        }
        MeshUtil.dispose(this);

        try {
            if (this.imageRequest) {
                this.imageRequest.abort();
                this.imageRequest.onload = null;
                this.imageRequest.onerror = null;
                this.imageRequest = null;
            }
        } catch (error) {
        }
    }
}